package com.raymond.smgp.session;

import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson.JSONObject;
import com.google.common.primitives.Bytes;
import com.raymond.client.constants.GlobalConstants;
import com.raymond.client.handler.RecvBusinessHandler;
import com.raymond.client.handler.RespBusinessHandler;
import com.raymond.client.msg.MessageManages;
import com.raymond.client.netty.AgreementDecoder;
import com.raymond.client.netty.MsgDecoder;
import com.raymond.client.netty.MsgEncoder;
import com.raymond.client.session.AbstractClientSession;
import com.raymond.client.thread.ThreadPool;
import com.raymond.client.utils.SequenceIdUtil;
import com.raymond.smgp.config.SmgpClientSocketConfig;
import com.raymond.smgp.msg.request.ActiveTestRequestMessage;
import com.raymond.smgp.msg.request.ConnectRequestMessage;
import com.raymond.smgp.msg.request.TerminateRequestMessage;
import com.raymond.smgp.msg.response.ConnectResponseMessage;
import io.netty.channel.Channel;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.Charset;
import java.util.Date;

/**
 * 简单的mq连接session
 *
 * @author :  raymond
 * @version :  V1.0
 * @date :  2022-11-01 10:25
 */
public class SmgpClientSession extends AbstractClientSession {

    private static final Logger logger = LoggerFactory.getLogger(SmgpClientSession.class);

    private int loginStatus = -1;

    SmgpClientSession(SmgpClientSessionManager sessionManager, SmgpClientSocketConfig socketConfig) {
        super(sessionManager, socketConfig);
    }

    @Override
    protected void fireChannelActive(Channel channel) {
        ChannelPipeline pipeline = channel.pipeline();
        SmgpClientSessionManager sessionManager = (SmgpClientSessionManager)super.sessionManager;
        pipeline.addFirst(new RecvBusinessHandler(sessionManager.getHandlerProcessors(), ThreadPool.CALLBACK.getCallBackThreadPool()));
        pipeline.addFirst(new RespBusinessHandler(msgManager));
        pipeline.addFirst(new MsgEncoder(sessionManager.getCodec()));
        pipeline.addFirst(new MsgDecoder(sessionManager.getCodec()));
        pipeline.addFirst(new IdleStateHandler(0, 0, 60));
        pipeline.addFirst(new AgreementDecoder());
        doLogin();
    }

    private void doLogin() {
        SmgpClientSocketConfig socketConfig = (SmgpClientSocketConfig) this.socketConfig;
        // TODO 发送连接请求 ,创建密码
        ConnectRequestMessage req = new ConnectRequestMessage(SequenceIdUtil.getSequenceId());
        req.setClientId(socketConfig.getClientId());
        String timestamp = getData();
        req.setTimestamp(Integer.parseInt(timestamp));
        req.setAuthenticatorClient(getAuthenticatorSource(socketConfig.getClientId(), socketConfig.getPassword(), timestamp, GlobalConstants.DEFAULT_TRANSPORT_CHARSET));
        req.setLoginMode(socketConfig.getLoginMode());
        req.setVersion((short) socketConfig.getVersion());
        loginStatus = -2;
        MessageManages messageManages = syncSend(req);
        loginStatus = messageManages.getResp() == null ? -2 : (int) ((ConnectResponseMessage)messageManages.getResp()).getStatus();
        logger.info("session Start :Send CmppConnectRequestMessage seq :{}, messageManages:{}",
                req.getSequenceId(), JSONObject.toJSONString(messageManages));
    }

    public static byte[] getAuthenticatorSource(String userName, String password, String timestamp, Charset charset) {
        byte[] userBytes = userName.getBytes(charset);
        byte[] passwordBytes = password.getBytes(charset);
        byte[] timestampBytes = timestamp.getBytes(charset);
        return MD5.create().digest(Bytes.concat(userBytes, new byte[7], passwordBytes, timestampBytes));
    }


    @Override
    public synchronized void shutdown() throws InterruptedException {
        syncSend(new TerminateRequestMessage(SequenceIdUtil.getSequenceId()));
        super.shutdown();
    }

    public int getLoginStatus() {
        return loginStatus;
    }

    public String getData() {
        return DateUtil.format(new Date(), "MMddHHmmss");
    }
    @Override
    public Object getHeartbeatRequest() {
        return new ActiveTestRequestMessage(SequenceIdUtil.getSequenceId());
    }
}
